package cn.piesat.scanning.service.impl;

import cn.piesat.scanning.business.dq1043.vo.MetaDataInDbVO;
import cn.piesat.scanning.dao.DbDmsSchedulerTaskFileRecordDAO;
import cn.piesat.scanning.dto.DbDmsSchedulerTaskFileRecordDTO;
import cn.piesat.scanning.utils.IpUtil;
import cn.piesat.scanning.utils.TaskRecordUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DbDmsSchedulerTaskFileRecordServiceImpl implements cn.piesat.scanning.service.DbDmsSchedulerTaskFileRecordService {

    @Autowired
    private DbDmsSchedulerTaskFileRecordDAO dbdmsSchedulerTaskFileRecordDAO;

    /**
     *  根据文件集合 准备数据阶段记录
     * @param taskId 任务Id
     * @param fileList 符合规范文件集合
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void prepareDataByFileList(String taskId, List<File> fileList) {
        if(fileList!=null && fileList.size()!=0){
            List<String> fileNameList = fileList.stream().map(File::getName).collect(Collectors.toList());
            prepareDataByFileNameList(taskId,fileNameList);
        }
    }

    /**
     * 根据文件名称集合 准备数据阶段记录
     * @param taskId 任务Id
     * @param fileNameList 符合规范文件集合
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void prepareDataByFileNameList(String taskId, List<String> fileNameList) {
        if(fileNameList!=null && fileNameList.size()!=0){
            //创建待保存对象
            List<DbDmsSchedulerTaskFileRecordDTO> saveList = fileNameList.stream().map(fileName -> createNewTaskFileRecord(taskId, fileName)).collect(Collectors.toList());
            //删除数据库重复的数据
//            dbdmsSchedulerTaskFileRecordDAO.deleteAllByTaskIdAndFileNameIn(taskId, fileNameList);
            //redis数据记录待执行数量
            TaskRecordUtils.increaseWaitCount(TaskRecordUtils.getHkey(taskId), saveList.size());
            //数据库待执行对象
            dbdmsSchedulerTaskFileRecordDAO.saveAll(saveList);
        }
    }

    /**
     * 根据文件名称集合 准备数据阶段记录
     * @param taskId 任务Id
     * @param fileNameList 符合规范文件集合
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void prepareDataByFileNameList(String taskId, List<String> fileNameList,  Map<String, MetaDataInDbVO> distinctRecordMap) {
        if(fileNameList!=null && fileNameList.size()!=0){
            //创建待保存对象
            List<DbDmsSchedulerTaskFileRecordDTO> saveList = fileNameList.stream().map(fileName -> createNewTaskFileRecord(taskId, fileName,distinctRecordMap.get(fileName).getTaskPlanId())).collect(Collectors.toList());
            //删除数据库重复的数据
//            dbdmsSchedulerTaskFileRecordDAO.deleteAllByTaskIdAndFileNameIn(taskId, fileNameList);
            //redis数据记录待执行数量
            TaskRecordUtils.increaseWaitCount(TaskRecordUtils.getHkey(taskId), saveList.size());
            //数据库待执行对象
            dbdmsSchedulerTaskFileRecordDAO.saveAll(saveList);
        }
    }

    @Override
    public DbDmsSchedulerTaskFileRecordDTO prepareDataByFileName(String taskId, String fileName,String taskPlanId) {
        if (StringUtils.isNotBlank(fileName)) {
            DbDmsSchedulerTaskFileRecordDTO dto = createNewTaskFileRecord(taskId, fileName,taskPlanId);
            TaskRecordUtils.increaseWaitCount(TaskRecordUtils.getHkey(taskId), 1);
            return dbdmsSchedulerTaskFileRecordDAO.save(dto);
        }
        return null;
    }

    @Override
    public DbDmsSchedulerTaskFileRecordDTO prepareDataByFileName(String taskPlanId,String taskId, String fileName, int incrWait) {
        if (StringUtils.isNotBlank(fileName)) {
            DbDmsSchedulerTaskFileRecordDTO dto = createNewTaskFileRecord(taskId, fileName,taskPlanId);
            TaskRecordUtils.increaseWaitCount(TaskRecordUtils.getHkey(taskId), incrWait);
            return dbdmsSchedulerTaskFileRecordDAO.save(dto);
        }
        return null;
    }

    /**
     * 数据执行
     * @param taskId 任务Id
     * @param fileName 文件名称
     */
    @Override
    public void dataExecution(String taskId, String fileName) {
        String hkey = TaskRecordUtils.getHkey(taskId);
        //redis数据记录变更执行数量
        TaskRecordUtils.increaseWaitCount(hkey,-1);
        TaskRecordUtils.increaseRunningCount(hkey,1);
        //查找数据
        DbDmsSchedulerTaskFileRecordDTO dto = dbdmsSchedulerTaskFileRecordDAO.findByTaskIdAndFileName(taskId, fileName);
        //更新状态
        if(dto!=null){
            dto.setState(1);
            dto.setExecServer(IpUtil.getLinuxLocalIp());
            dto.setStartTime(new Date());
            dbdmsSchedulerTaskFileRecordDAO.save(dto);
        }
    }

    @Override
    @Transactional
    public void dataExecutionBatch(String taskId, List<String> fileNames) {
        if (CollectionUtils.isEmpty(fileNames)) {
            return;
        }

        String hkey = TaskRecordUtils.getHkey(taskId);
        //redis数据记录变更执行数量
        TaskRecordUtils.increaseWaitCount(hkey,-fileNames.size());
        TaskRecordUtils.increaseRunningCount(hkey, fileNames.size());
        //查找数据
        List<DbDmsSchedulerTaskFileRecordDTO> dtos = dbdmsSchedulerTaskFileRecordDAO.findByTaskIdAndFileNames(taskId, fileNames);
        List<String> ids = dtos.stream().map(DbDmsSchedulerTaskFileRecordDTO::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ids)) {
            //更新状态
            dbdmsSchedulerTaskFileRecordDAO.updateStateAndExecServerBatch(1, IpUtil.getLinuxLocalIp(), new Date(), ids);
        }
    }

    /**
     * 数据执行，存在重复文件名
     * @param taskId
     * @param fileName
     */
    @Override
    public void dataRepeatExecution(String taskId, String fileName) {
        String hkey = TaskRecordUtils.getHkey(taskId);
        //redis数据记录变更执行数量
        TaskRecordUtils.increaseWaitCount(hkey,-1);
        TaskRecordUtils.increaseRunningCount(hkey,1);
        //查找数据
        List<DbDmsSchedulerTaskFileRecordDTO> dtoList = dbdmsSchedulerTaskFileRecordDAO.selectByTaskIdAndFileName(taskId, fileName);
        //更新状态（重复的文件同时都修改状态）
        for (DbDmsSchedulerTaskFileRecordDTO dto : dtoList) {
            dto.setState(1);
            dto.setStartTime(new Date());
            dto.setExecServer(IpUtil.getLinuxLocalIp());
        }
        dbdmsSchedulerTaskFileRecordDAO.saveAll(dtoList);
    }

    /**
     * 数据结果记录
     * @param taskId 任务Id
     * @param fileName 文件名称
     * @param resultStatus 状态
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dataResults(String taskId, String fileName, boolean resultStatus) {
        int status = 3;
        String hkey = TaskRecordUtils.getHkey(taskId);
        TaskRecordUtils.increaseRunningCount(hkey,-1);
        if(resultStatus){
            status = 2;
        }else{
            TaskRecordUtils.increaseFailCount(hkey,1);
        }
        //查找数据
        DbDmsSchedulerTaskFileRecordDTO dto = dbdmsSchedulerTaskFileRecordDAO.findByTaskIdAndFileName(taskId, fileName);
        if(dto!=null){
            dto.setState(status);
            dto.setEndTime(new Date());
            dbdmsSchedulerTaskFileRecordDAO.save(dto);
        }
    }

    @Override
    @Transactional
    public void dataResultsBatch(String taskId, List<String> fileNames, boolean resultStatus) {
        if (CollectionUtils.isEmpty(fileNames)) {
            return;
        }

        int status = 3;
        String hkey = TaskRecordUtils.getHkey(taskId);
        TaskRecordUtils.increaseRunningCount(hkey,-fileNames.size());
        if(resultStatus){
            status = 2;
        }else{
            TaskRecordUtils.increaseFailCount(hkey,fileNames.size());
        }
        //查找数据
        List<DbDmsSchedulerTaskFileRecordDTO> dtos = dbdmsSchedulerTaskFileRecordDAO.findByTaskIdAndFileNames(taskId, fileNames);
        List<String> ids = dtos.stream().map(DbDmsSchedulerTaskFileRecordDTO::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ids)) {
            dbdmsSchedulerTaskFileRecordDAO.updateStateBatch(status, new Date(), ids);
        }
    }

    /**
     * 数据结果记录（存在重复数据）
     * @param taskId
     * @param fileName
     * @param resultStatus
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dataRepeatResults(String taskId, String fileName, boolean resultStatus) {
        int status = 3;
        String hkey = TaskRecordUtils.getHkey(taskId);
        TaskRecordUtils.increaseRunningCount(hkey,-1);
        if(resultStatus){
            status = 2;
        }else{
            TaskRecordUtils.increaseFailCount(hkey,1);
        }
        //查找数据
        List<DbDmsSchedulerTaskFileRecordDTO> dtoList = dbdmsSchedulerTaskFileRecordDAO.selectByTaskIdAndFileName(taskId, fileName);
        for (DbDmsSchedulerTaskFileRecordDTO dto : dtoList) {
            dto.setState(status);
            dto.setEndTime(new Date());
        }
        dbdmsSchedulerTaskFileRecordDAO.saveAll(dtoList);
    }

    /**
     * 根据记录Id查询信息
     * @param id 记录ID
     * @return
     */
    @Override
    public DbDmsSchedulerTaskFileRecordDTO findById(String id) {
        Optional<DbDmsSchedulerTaskFileRecordDTO> optional = dbdmsSchedulerTaskFileRecordDAO.findById(id);
        return optional.orElse(null);
    }

    /**
     * 数据重做
     * @param taskFileRecordDTO 任务执行记录对象
     */
    @Override
    public void dataRedo(DbDmsSchedulerTaskFileRecordDTO taskFileRecordDTO) {
        if (taskFileRecordDTO != null) {
            String hkey = TaskRecordUtils.getHkey(taskFileRecordDTO.getTaskId());
            if (taskFileRecordDTO.getState() >= 3) {
                TaskRecordUtils.increaseFailCount(hkey,-1);
            } else {
                TaskRecordUtils.increaseWaitCount(hkey,1);
            }
            taskFileRecordDTO.setState(0);
            taskFileRecordDTO.setStartTime(null);
            taskFileRecordDTO.setEndTime(null);
            taskFileRecordDTO.setExecServer(null);
            taskFileRecordDTO.setCreateTime(new Date());
            dbdmsSchedulerTaskFileRecordDAO.save(taskFileRecordDTO);
        }
    }

    /**
     * 添加实体类
     * @param dto
     */
    @Override
    public void save(DbDmsSchedulerTaskFileRecordDTO dto) {
        try{
            dbdmsSchedulerTaskFileRecordDAO.save(dto);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 重做时修改状态，删除失败的状态，重新归置为等待状态
     * @param taskId
     * @param fileNameList
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void redoDataStatus(String taskId, List<String> fileNameList) {
        List<DbDmsSchedulerTaskFileRecordDTO> reDtoList = null;
        long failCount = 0;
        if (StringUtils.isNotBlank(taskId) && Objects.nonNull(fileNameList) && !fileNameList.isEmpty()) {
            List<DbDmsSchedulerTaskFileRecordDTO> dtoList = dbdmsSchedulerTaskFileRecordDAO.findByTaskIdAndFileNameIn(taskId, fileNameList);
            failCount = dtoList.stream().filter(dto -> dto.getState() == 3).count();
            reDtoList = dtoList.stream().map(dto -> {
                dto.setStartTime(null);
                dto.setEndTime(null);
                dto.setState(0);
                dto.setExecServer(null);
                dto.setCreateTime(new Date());
                return dto;
            }).collect(Collectors.toList());
            dbdmsSchedulerTaskFileRecordDAO.saveAll(reDtoList);
        }
        if (Objects.nonNull(reDtoList)) {
            String hkey = TaskRecordUtils.getHkey(taskId);
            //redis数据记录变更执行数量
            TaskRecordUtils.increaseWaitCount(hkey,fileNameList.size());
            TaskRecordUtils.increaseFailCount(hkey,-1 * failCount);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByTaskIdAndFileName(String taskId, String fileName) {
        dbdmsSchedulerTaskFileRecordDAO.deleteByTaskIdAndFileName(taskId,fileName);
    }

    @Override
    public DbDmsSchedulerTaskFileRecordDTO findByTaskIdAndFileName(String taskId, String fileName) {
        return dbdmsSchedulerTaskFileRecordDAO.findByTaskIdAndFileName(taskId,fileName);
    }

    @Override
    public List<DbDmsSchedulerTaskFileRecordDTO> findAllByTaskIdAndFileNameIn(String taskId, List<String> fileNameList) {
        return dbdmsSchedulerTaskFileRecordDAO.findByTaskIdAndFileNameIn(taskId,fileNameList);
    }

    @Override
    public List<String> findFileNameListByTaskId(String taskId) {
        return dbdmsSchedulerTaskFileRecordDAO.findFileNameListByTaskId(taskId);
    }

    @Override
    public List<DbDmsSchedulerTaskFileRecordDTO> findByTaskId(String taskId) {
        return dbdmsSchedulerTaskFileRecordDAO.findByTaskId(taskId);
    }

    @Override
    public List<DbDmsSchedulerTaskFileRecordDTO> findRedoTasks(String taskId) {
        return dbdmsSchedulerTaskFileRecordDAO
                .findFileNameListByTaskIdAndStateAndRedoCountLessThan(taskId,7,48);
    }

    @Override
    public Set<String> listByTaskId(String taskId) {
        List<String> datalist = dbdmsSchedulerTaskFileRecordDAO.listByTaskId(taskId);
        return new LinkedHashSet<>(datalist);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByTaskPlanIdIn(List<String> taskPlanIds) {
        dbdmsSchedulerTaskFileRecordDAO.deleteByTaskPlanIdIn(taskPlanIds);
    }

    @Override
    public List<DbDmsSchedulerTaskFileRecordDTO> findByFileNameList(List<String> execFileNameList,String taskId) {
        return dbdmsSchedulerTaskFileRecordDAO.findByFileNameList(execFileNameList,taskId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTaskPlanIdByTaskIdAndFileName(String taskId, String fileName, String taskPlanId) {
        dbdmsSchedulerTaskFileRecordDAO.updateTaskPlanIdByTaskIdAndFileName(taskId,fileName,taskPlanId);
    }

    @Override
    public List<DbDmsSchedulerTaskFileRecordDTO> findByTaskPlanIdAndStateNot(String taskPlanId,int state) {
        return dbdmsSchedulerTaskFileRecordDAO.findByTaskPlanIdAndStateNot(taskPlanId,state);
    }

    @Override
    public List<DbDmsSchedulerTaskFileRecordDTO> findByFileNameLikeAndStateLessThan(String fileDateBei, int state) {
        return dbdmsSchedulerTaskFileRecordDAO.findByFileNameLikeAndStateLessThan(fileDateBei,state);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByFileNameLikeAndTaskPlanIdNotNull(String fileDateBei) {
        dbdmsSchedulerTaskFileRecordDAO.deleteByFileNameLikeAndTaskPlanIdNotNull(fileDateBei);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByFileNameIn(List<String> l0FileNameList) {
        dbdmsSchedulerTaskFileRecordDAO.deleteByFileNameIn(l0FileNameList);
    }

    @Override
    public List<DbDmsSchedulerTaskFileRecordDTO> findByTaskIdAndFileNameIn(String id, List<String> allNameList) {
        return dbdmsSchedulerTaskFileRecordDAO.findByTaskIdAndFileNameIn(id,allNameList);
    }

    /**
     * 组装新的数据对象
     * @param taskId 任务Id
     * @param fileName 文件名称
     * @return
     */
    private DbDmsSchedulerTaskFileRecordDTO createNewTaskFileRecord(String taskId,String fileName){
        DbDmsSchedulerTaskFileRecordDTO dbDmsSchedulerTaskFileRecordDTO = new DbDmsSchedulerTaskFileRecordDTO();
        dbDmsSchedulerTaskFileRecordDTO.setTaskId(taskId);
        dbDmsSchedulerTaskFileRecordDTO.setFileName(fileName);
        dbDmsSchedulerTaskFileRecordDTO.setState(0);
        dbDmsSchedulerTaskFileRecordDTO.setCreateTime(new Date());
        return dbDmsSchedulerTaskFileRecordDTO;
    }
    private DbDmsSchedulerTaskFileRecordDTO createNewTaskFileRecord(String taskId,String fileName,String taskPlanId){
        DbDmsSchedulerTaskFileRecordDTO dbDmsSchedulerTaskFileRecordDTO = new DbDmsSchedulerTaskFileRecordDTO();
        dbDmsSchedulerTaskFileRecordDTO.setTaskId(taskId);
        dbDmsSchedulerTaskFileRecordDTO.setFileName(fileName);
        dbDmsSchedulerTaskFileRecordDTO.setTaskPlanId(taskPlanId);
        dbDmsSchedulerTaskFileRecordDTO.setState(0);
        dbDmsSchedulerTaskFileRecordDTO.setCreateTime(new Date());
        return dbDmsSchedulerTaskFileRecordDTO;
    }
}
